//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<lock.inl>
///	@path	~/src/lib/system/
///	@date	2007/06/23
///	@desc	lock implementation.

#include "lib/system/lock.h"

#include "config/os.h"

namespace xeres {

	// ctor
	inline ThreadLock::ThreadLock( void )
	{
		m_lockImpl = new CRITICAL_SECTION;
		::InitializeCriticalSection( (CRITICAL_SECTION*)m_lockImpl );
	}
	
	// dtor
	inline ThreadLock::~ThreadLock( void )
	{
		::DeleteCriticalSection( (CRITICAL_SECTION*) m_lockImpl );
		delete (CRITICAL_SECTION*)m_lockImpl;
	}

	// acquire lock
	inline void ThreadLock::Acquire( void )
	{
		::EnterCriticalSection( (CRITICAL_SECTION*)m_lockImpl );
	}

	// release lock
	inline void ThreadLock::Release( void )
	{
		::LeaveCriticalSection( (CRITICAL_SECTION*)m_lockImpl );
	}

	// try acquire lock
	inline bool ThreadLock::TryAcquire( const Time& wait )
	{
		Time t = Time::Now();
		while( ::TryEnterCriticalSection( (CRITICAL_SECTION*)m_lockImpl ) == TRUE )
		{
			// spin self
			for( int b = 0 ; b < 50 ; ++b )
				;
			// check
			if( ( Time::Now() - t ) > wait )
				return false;
			::SwitchToThread();
		}
		return true;
	}

	// TryAcquire
	inline bool ThreadLock::TryAcquire( void )
	{
		return ::TryEnterCriticalSection( (CRITICAL_SECTION*)m_lockImpl ) == TRUE;
	}

	// ctor
	inline SpinLock::SpinLock( void )
	{
		spin_lock_init( (int*)&m_monitor );
	}

	// dtor
	inline SpinLock::~SpinLock( void )
	{
	}

	// acquire lock
	inline void SpinLock::Acquire( void )
	{
		spin_lock_lock( (int*)&m_monitor );
	}

	// release lock
	inline void SpinLock::Release( void )
	{
		spin_lock_unlock( (int*)&m_monitor );
	}

	// try acquire lock
	inline bool SpinLock::TryAcquire( const Time& wait )
	{
		Time stamp = Time::Now();
		do 
		{
			if( spin_lock_trylock( (int*)&m_monitor ) == LOCK_FREE )
				return true;
		} while( ( Time::Now() - stamp ) < wait );
		return false;
	}

	// try acquire lock
	inline bool SpinLock::TryAcquire( void )
	{
		return spin_lock_trylock( (int*)&m_monitor ) == LOCK_FREE;
	}

} // namespace xeres
